﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.MemoryMappedFiles;

namespace ConeDBServerNS
{
    public class ConeDatabase : IList<ConeEntity>, IEnumerator<ConeEntity>, IDisposable
    {
        private string _DatabaseName;
        private string _FileLocation;
        private MemoryMappedFile _Database;
        private const long StorageSize = 4294967296;
        private long index = 0;

        public string DatabaseName
        {
            get { return _DatabaseName; }
            private set { _DatabaseName = Path.GetFileNameWithoutExtension(value); }
        }
        public string FileLocation
        {
            get { return _FileLocation; }
            private set { _FileLocation = value; }
        }
        public readonly ConeDBServer Owner;


        public ConeDatabase(ref ConeDBServer Server)
        {
            this.Owner = Server;
        }

        public void CreateDatabase(string FileName)
        {
            FileInfo f = GetFileInfo(FileName);

            if (f.Exists)
            {
                throw new IOException("Cannot overwrite existing database");
            }
            else
            {
                Directory.CreateDirectory(ConeProperties.ConeDatabaseLocation);
                var NewDB = f.Create();
                LoadDatabase(ref NewDB);
            }
        }

        public void OpenDatabase(string FileName)
        {
            FileInfo f = GetFileInfo(FileName);
            if (f.Exists)
            {
                var NewDB = f.Open(FileMode.Open);
                LoadDatabase(ref NewDB);
            }
            else
            {
                throw new IOException("Database does not exist");
            }

        }

        private FileInfo GetFileInfo(string FileName)
        {
            string FilePath = Path.Combine(ConeProperties.ConeDatabaseLocation, FileName);
            FileInfo f = new FileInfo(FilePath);
            return f;
        }
        private void LoadDatabase(ref FileStream f)
        {
            string name = Path.GetFileNameWithoutExtension(f.Name);
            this._Database = MemoryMappedFile.CreateFromFile(f, name, StorageSize, MemoryMappedFileAccess.ReadWrite, new MemoryMappedFileSecurity(), HandleInheritability.None, false);
            this.DatabaseName = name;
            this.FileLocation = f.Name;
            f.Close();
            f.Dispose();
        }

        int IList<ConeEntity>.IndexOf(ConeEntity item)
        {
            throw new NotImplementedException();
        }

        void IList<ConeEntity>.Insert(int index, ConeEntity item)
        {
            throw new NotImplementedException();
        }

        void IList<ConeEntity>.RemoveAt(int index)
        {
            throw new NotImplementedException();
        }

        ConeEntity IList<ConeEntity>.this[int index]
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        void ICollection<ConeEntity>.Add(ConeEntity item)
        {
            using (var db = this._Database.CreateViewAccessor())
            {
                var entity = item.GetBinary();
                var length = item.GetBinary().Length;
                db.WriteArray<byte>(this.index, entity, 0, length);
                this.index += length;
            }
        }

        void ICollection<ConeEntity>.Clear()
        {
            throw new NotImplementedException();
        }

        bool ICollection<ConeEntity>.Contains(ConeEntity item)
        {
            throw new NotImplementedException();
        }

        void ICollection<ConeEntity>.CopyTo(ConeEntity[] array, int arrayIndex)
        {
            throw new NotImplementedException();
        }

        int ICollection<ConeEntity>.Count
        {
            get { throw new NotImplementedException(); }
        }

        bool ICollection<ConeEntity>.IsReadOnly
        {
            get { throw new NotImplementedException(); }
        }

        bool ICollection<ConeEntity>.Remove(ConeEntity item)
        {
            throw new NotImplementedException();
        }

        IEnumerator<ConeEntity> IEnumerable<ConeEntity>.GetEnumerator()
        {
            throw new NotImplementedException();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }

        ConeEntity IEnumerator<ConeEntity>.Current
        {
            get { throw new NotImplementedException(); }
        }

        void IDisposable.Dispose()
        {
            this._Database.Dispose();
        }

        object System.Collections.IEnumerator.Current
        {
            get { throw new NotImplementedException(); }
        }

        bool System.Collections.IEnumerator.MoveNext()
        {
            throw new NotImplementedException();
        }

        void System.Collections.IEnumerator.Reset()
        {
            throw new NotImplementedException();
        }
    }
}
